package com.hu.web.controller.business;

import java.util.List;
import javax.servlet.http.HttpServletResponse;

import com.alibaba.excel.EasyExcel;
import com.hu.system.listener.PurchaseInboundImportListener;
import com.hu.system.mapper.PurchaseInboundMapper;
import com.hu.system.mapper.ProductInfoMapper;
import com.hu.system.mapper.StockInboundMapper;
import com.hu.system.service.IProductInfoService;
import com.hu.system.service.IShopInfoService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.hu.common.annotation.Log;
import com.hu.common.core.controller.BaseController;
import com.hu.common.core.domain.AjaxResult;
import com.hu.common.enums.BusinessType;
import com.hu.system.domain.PurchaseInbound;
import com.hu.system.service.IPurchaseInboundService;
import com.hu.common.utils.poi.ExcelUtil;
import com.hu.common.core.page.TableDataInfo;

/**
 * 采购管理Controller
 *
 * @author hu
 * @date 2025-01-21
 */
@RestController
@RequestMapping("/business/purchase")
public class PurchaseInboundController extends BaseController {
    private static final Logger log = LoggerFactory.getLogger(PurchaseInboundController.class);

    /** 表头扫描行数限制 */
    private static final int HEADER_SCAN_LIMIT = 10;
    
    /** 表头识别关键字段 */
    private static final String[] HEADER_KEYWORDS = {"SKU ID", "产品名称", "所属店铺"};

    @Autowired
    private IPurchaseInboundService purchaseInboundService;

    @Autowired
    private IProductInfoService productInfoService;

    @Autowired
    private IShopInfoService shopInfoService;

    @Autowired
    private PurchaseInboundMapper purchaseInboundMapper;

    @Autowired
    private ProductInfoMapper productInfoMapper;

    @Autowired
    private StockInboundMapper stockInboundMapper;

    /**
     * 查询采购记录列表
     */
    @PreAuthorize("@ss.hasPermi('purchase:manage:list')")
    @GetMapping("/list")
    public AjaxResult list(PurchaseInbound purchaseInbound) {
        startPage();
        List<PurchaseInbound> list = purchaseInboundService.selectPurchaseInboundList(purchaseInbound);
        TableDataInfo dataTable = getDataTable(list);

        // 获取统计数据（基于全部符合条件的数据，而不是分页数据）
        com.hu.system.domain.PurchaseStatistics statistics = purchaseInboundService.selectPurchaseStatistics(purchaseInbound);

        // 使用 AjaxResult 返回，包含分页数据和统计数据
        AjaxResult result = AjaxResult.success();
        result.put("rows", dataTable.getRows());
        result.put("total", dataTable.getTotal());
        result.put("statistics", statistics);

        return result;
    }

    /**
     * 导出采购记录列表
     */
    @PreAuthorize("@ss.hasPermi('purchase:manage:export')")
    @Log(title = "采购管理", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, PurchaseInbound purchaseInbound) {
        List<PurchaseInbound> list = purchaseInboundService.selectPurchaseInboundList(purchaseInbound);
        ExcelUtil<PurchaseInbound> util = new ExcelUtil<PurchaseInbound>(PurchaseInbound.class);
        util.exportExcel(response, list, "采购管理数据");
    }

    /**
     * 获取采购记录详细信息
     */
    @PreAuthorize("@ss.hasPermi('purchase:manage:query')")
    @GetMapping(value = "/{inboundId}")
    public AjaxResult getInfo(@PathVariable("inboundId") Long inboundId) {
        PurchaseInbound inbound = purchaseInboundService.selectPurchaseInboundByInboundId(inboundId);
        if (inbound == null) {
            return error("您没有权限查看该采购记录或记录不存在");
        }
        return success(inbound);
    }

    /**
     * 新增采购记录
     */
    @PreAuthorize("@ss.hasPermi('purchase:manage:add')")
    @Log(title = "采购管理", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody PurchaseInbound purchaseInbound) {
        return toAjax(purchaseInboundService.insertPurchaseInbound(purchaseInbound));
    }

    /**
     * 修改采购记录
     */
    @PreAuthorize("@ss.hasPermi('purchase:manage:edit')")
    @Log(title = "采购管理", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody PurchaseInbound purchaseInbound) {
        return toAjax(purchaseInboundService.updatePurchaseInbound(purchaseInbound));
    }

    /**
     * 删除采购记录
     */
    @PreAuthorize("@ss.hasPermi('purchase:manage:remove')")
    @Log(title = "采购管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{inboundIds}")
    public AjaxResult remove(@PathVariable Long[] inboundIds) {
        return toAjax(purchaseInboundService.deletePurchaseInboundByInboundIds(inboundIds));
    }

    /**
     * 采购统计（与列表查询共用接口，前端根据需要调用）
     */
    @PreAuthorize("@ss.hasPermi('purchase:manage:query')")
    @GetMapping("/statistics")
    public TableDataInfo statistics(PurchaseInbound purchaseInbound) {
        startPage();
        List<PurchaseInbound> list = purchaseInboundService.selectPurchaseInboundList(purchaseInbound);
        return getDataTable(list);
    }

    /**
     * 导入采购入库数据
     * 必须从Excel的"所属店铺"列读取店铺信息，店铺不存在则自动创建
     */
    @PreAuthorize("@ss.hasPermi('purchase:inbound:import')")
    @Log(title = "采购入库", businessType = BusinessType.IMPORT)
    @PostMapping("/importData")
    public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception {
        // 将文件转为字节数组，以便多次读取（第一次识别表头，第二次导入数据）
        byte[] fileBytes = file.getBytes();

        // 第一步：动态识别表头行和列映射关系
        HeaderDetectionResult headerResult = detectHeaderRowAndColumns(new java.io.ByteArrayInputStream(fileBytes));
        if (headerResult == null || headerResult.headRowNumber == -1) {
            return error("未找到有效的表头行，请确保Excel中包含'SKU ID'或'产品名称'列");
        }
        log.info("表头位于第{}行，识别{}个有效列", headerResult.headRowNumber + 1, headerResult.columnMap.size());

        // 第二步：使用手动映射模式读取数据（完全控制读取位置）
        PurchaseInboundImportListener listener = new PurchaseInboundImportListener(
                productInfoService,
                shopInfoService,
                purchaseInboundMapper,
                productInfoMapper,
                stockInboundMapper,
                getUsername(),
                headerResult.headRowNumber,
                headerResult.columnMap  // 传递列映射关系
        );

        // 使用无模型读取，从表头下一行开始读取数据
        EasyExcel.read(new java.io.ByteArrayInputStream(fileBytes), listener)
                .sheet(0)
                .headRowNumber(null)  // 不使用自动表头识别，由listener控制
                .doRead();

        // 获取导入结果
        String message = listener.getResult();
        return success(message);
    }

    /**
     * 表头检测结果
     */
    private static class HeaderDetectionResult {
        int headRowNumber;
        java.util.Map<String, Integer> columnMap;
        
        HeaderDetectionResult(int headRowNumber, java.util.Map<String, Integer> columnMap) {
            this.headRowNumber = headRowNumber;
            this.columnMap = columnMap;
        }
    }
    
    /**
     * 动态识别表头行并建立列映射
     *
     * @param inputStream Excel文件输入流
     * @return 表头检测结果（包含行号和列映射）
     */
    private HeaderDetectionResult detectHeaderRowAndColumns(java.io.InputStream inputStream) {
        final int[] headerRowNumber = {-1};
        final java.util.Map<String, Integer>[] columnMapHolder = new java.util.Map[]{null};

        try {
            // 使用无模型读取，只读取前N行
            EasyExcel.read(inputStream, new com.alibaba.excel.read.listener.ReadListener<java.util.Map<Integer, String>>() {
                @Override
                public void invoke(java.util.Map<Integer, String> data, com.alibaba.excel.context.AnalysisContext context) {
                    // 获取真实的Excel行号
                    int realRowIndex = context.readRowHolder().getRowIndex();
                    
                    // 检查当前行是否包含关键字段
                    if (headerRowNumber[0] == -1 && realRowIndex < HEADER_SCAN_LIMIT) {
                        String rowContent = String.join("|", data.values());

                        // 如果包含任一关键字段，认为是表头行
                        for (String keyword : HEADER_KEYWORDS) {
                            if (rowContent.contains(keyword)) {
                                headerRowNumber[0] = realRowIndex;
                                
                                // 建立列映射关系：列名 -> 列索引
                                java.util.Map<String, Integer> columnMap = new java.util.HashMap<>();
                                for (java.util.Map.Entry<Integer, String> entry : data.entrySet()) {
                                    String columnName = entry.getValue();
                                    if (columnName != null && !columnName.trim().isEmpty()) {
                                        columnMap.put(columnName.trim(), entry.getKey());
                                    }
                                }
                                columnMapHolder[0] = columnMap;
                                
                                log.info("识别到表头行：第{}行", realRowIndex + 1);
                                break;
                            }
                        }
                    }

                    // 找到表头或超过限制行数就停止
                    if (headerRowNumber[0] != -1 || realRowIndex >= HEADER_SCAN_LIMIT) {
                        throw new com.alibaba.excel.exception.ExcelAnalysisStopException();
                    }
                }

                @Override
                public void doAfterAllAnalysed(com.alibaba.excel.context.AnalysisContext context) {
                    // 读取完成
                }
            }).sheet(0).headRowNumber(null).doRead();  // 不指定表头，原始读取

        } catch (com.alibaba.excel.exception.ExcelAnalysisStopException e) {
            // 正常停止，已找到表头
        } catch (Exception e) {
            log.error("识别表头行失败", e);
        }

        if (headerRowNumber[0] != -1 && columnMapHolder[0] != null) {
            return new HeaderDetectionResult(headerRowNumber[0], columnMapHolder[0]);
        }
        return null;
    }

    /**
     * 下载导入模板
     */
    @PostMapping("/importTemplate")
    public void importTemplate(HttpServletResponse response) {
        ExcelUtil<PurchaseInbound> util = new ExcelUtil<PurchaseInbound>(PurchaseInbound.class);
        util.importTemplateExcel(response, "采购入库数据");
    }
}

